home *** CD-ROM | disk | FTP | other *** search
/ Inter.Net 55-1 / Inter.Net 55-1.iso / CBuilder / Setup / BCB / data.z / atlwin.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-02-09  |  17.6 KB  |  696 lines

  1. // This is a part of the Active Template Library.
  2. // Copyright (C) 1996-1997 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Active Template Library Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Active Template Library product.
  10.  
  11. #ifndef __ATLWIN_H__
  12.     #error atlwin.cpp requires atlwin.h to be included first
  13. #endif
  14.  
  15. #ifndef ATL_NO_NAMESPACE
  16. namespace ATL
  17. {
  18. #endif
  19.  
  20. /////////////////////////////////////////////////////////////////////////////
  21. // CWndProcThunk
  22.  
  23. void CWndProcThunk::Init(WNDPROC proc, void* pThis)
  24. {
  25. #if defined(_M_PPC)
  26. #error PPC not yet implemented
  27. #elif defined (_M_ALPHA)
  28.     thunk.ldah_at = 0x279f0000 | HIWORD(proc);
  29.     thunk.ldah_a0 = 0x261f0000 | HIWORD(pThis);
  30.     thunk.lda_at = 0x239c0000 | LOWORD(proc);
  31.     thunk.lda_a0 = 0x22100000 | LOWORD(pThis);
  32.     thunk.jmp = 0x6bfc0000;
  33. #elif defined (_M_IX86)
  34.     thunk.m_mov = 0xb9;
  35.     thunk.m_this = (DWORD)pThis;
  36.     thunk.m_jmp = 0xe9;
  37.     thunk.m_relproc = (int)proc - ((int)this+sizeof(_WndProcThunk));
  38. #endif
  39. }
  40.  
  41. /////////////////////////////////////////////////////////////////////////////
  42. // CWindow
  43.  
  44. HWND CWindow::GetDescendantWindow(int nID) const
  45. {
  46.     _ASSERTE(::IsWindow(m_hWnd));
  47.  
  48.     // GetDlgItem recursive (return first found)
  49.     // breadth-first for 1 level, then depth-first for next level
  50.  
  51.     // use GetDlgItem since it is a fast USER function
  52.     HWND hWndChild, hWndTmp;
  53.     CWindow wnd;
  54.     if((hWndChild = ::GetDlgItem(m_hWnd, nID)) != NULL)
  55.     {
  56.         if(::GetTopWindow(hWndChild) != NULL)
  57.         {
  58.             // children with the same ID as their parent have priority
  59.             wnd.Attach(hWndChild);
  60.             hWndTmp = wnd.GetDescendantWindow(nID);
  61.             if(hWndTmp != NULL)
  62.                 return hWndTmp;
  63.         }
  64.         return hWndChild;
  65.     }
  66.  
  67.     // walk each child
  68.     for(hWndChild = ::GetTopWindow(m_hWnd); hWndChild != NULL;
  69.         hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
  70.     {
  71.         wnd.Attach(hWndChild);
  72.         hWndTmp = wnd.GetDescendantWindow(nID);
  73.         if(hWndTmp != NULL)
  74.             return hWndTmp;
  75.     }
  76.  
  77.     return NULL;    // not found
  78. }
  79.  
  80. void CWindow::SendMessageToDescendants(UINT message, WPARAM wParam/*= 0*/, LPARAM lParam/*= 0*/, BOOL bDeep/* = TRUE*/)
  81. {
  82.     CWindow wnd;
  83.     for(HWND hWndChild = ::GetTopWindow(m_hWnd); hWndChild != NULL;
  84.         hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
  85.     {
  86.         ::SendMessage(hWndChild, message, wParam, lParam);
  87.  
  88.         if(bDeep && ::GetTopWindow(hWndChild) != NULL)
  89.         {
  90.             // send to child windows after parent
  91.             wnd.Attach(hWndChild);
  92.             wnd.SendMessageToDescendants(message, wParam, lParam, bDeep);
  93.         }
  94.     }
  95. }
  96.  
  97. BOOL CWindow::CenterWindow(HWND hWndCenter/* = NULL*/)
  98. {
  99.     _ASSERTE(::IsWindow(m_hWnd));
  100.  
  101.     // determine owner window to center against
  102.     DWORD dwStyle = GetStyle();
  103.     if(hWndCenter == NULL)
  104.     {
  105.         if(dwStyle & WS_CHILD)
  106.             hWndCenter = ::GetParent(m_hWnd);
  107.         else
  108.             hWndCenter = ::GetWindow(m_hWnd, GW_OWNER);
  109.     }
  110.  
  111.     // get coordinates of the window relative to its parent
  112.     RECT rcDlg;
  113.     ::GetWindowRect(m_hWnd, &rcDlg);
  114.     RECT rcArea;
  115.     RECT rcCenter;
  116.     HWND hWndParent;
  117.     if(!(dwStyle & WS_CHILD))
  118.     {
  119.         // don't center against invisible or minimized windows
  120.         if(hWndCenter != NULL)
  121.         {
  122.             DWORD dwStyle = ::GetWindowLong(hWndCenter, GWL_STYLE);
  123.             if(!(dwStyle & WS_VISIBLE) || (dwStyle & WS_MINIMIZE))
  124.                 hWndCenter = NULL;
  125.         }
  126.  
  127.         // center within screen coordinates
  128.         ::SystemParametersInfo(SPI_GETWORKAREA, NULL, &rcArea, NULL);
  129.  
  130.         if(hWndCenter == NULL)
  131.             rcCenter = rcArea;
  132.         else
  133.             ::GetWindowRect(hWndCenter, &rcCenter);
  134.     }
  135.     else
  136.     {
  137.         // center within parent client coordinates
  138.         hWndParent = ::GetParent(m_hWnd);
  139.         _ASSERTE(::IsWindow(hWndParent));
  140.  
  141.         ::GetClientRect(hWndParent, &rcArea);
  142.         _ASSERTE(::IsWindow(hWndCenter));
  143.         ::GetClientRect(hWndCenter, &rcCenter);
  144.         ::MapWindowPoints(hWndCenter, hWndParent, (POINT*)&rcCenter, 2);
  145.     }
  146.  
  147.     int DlgWidth = rcDlg.right - rcDlg.left;
  148.     int DlgHeight = rcDlg.bottom - rcDlg.top;
  149.  
  150.     // find dialog's upper left based on rcCenter
  151.     int xLeft = (rcCenter.left + rcCenter.right) / 2 - DlgWidth / 2;
  152.     int yTop = (rcCenter.top + rcCenter.bottom) / 2 - DlgHeight / 2;
  153.  
  154.     // if the dialog is outside the screen, move it inside
  155.     if(xLeft < rcArea.left)
  156.         xLeft = rcArea.left;
  157.     else if(xLeft + DlgWidth > rcArea.right)
  158.         xLeft = rcArea.right - DlgWidth;
  159.  
  160.     if(yTop < rcArea.top)
  161.         yTop = rcArea.top;
  162.     else if(yTop + DlgHeight > rcArea.bottom)
  163.         yTop = rcArea.bottom - DlgHeight;
  164.  
  165.     // map screen coordinates to child coordinates
  166.     return ::SetWindowPos(m_hWnd, NULL, xLeft, yTop, -1, -1,
  167.         SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
  168. }
  169.  
  170. BOOL CWindow::ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags)
  171. {
  172.     _ASSERTE(::IsWindow(m_hWnd));
  173.  
  174.     DWORD dwStyle = ::GetWindowLong(m_hWnd, GWL_STYLE);
  175.     DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd;
  176.     if(dwStyle == dwNewStyle)
  177.         return FALSE;
  178.  
  179.     ::SetWindowLong(m_hWnd, GWL_STYLE, dwNewStyle);
  180.     if(nFlags != 0)
  181.     {
  182.         ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0,
  183.             SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags);
  184.     }
  185.  
  186.     return TRUE;
  187. }
  188.  
  189. BOOL CWindow::ModifyStyleEx(DWORD dwRemove, DWORD dwAdd, UINT nFlags)
  190. {
  191.     _ASSERTE(::IsWindow(m_hWnd));
  192.  
  193.     DWORD dwStyle = ::GetWindowLong(m_hWnd, GWL_EXSTYLE);
  194.     DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd;
  195.     if(dwStyle == dwNewStyle)
  196.         return FALSE;
  197.  
  198.     ::SetWindowLong(m_hWnd, GWL_EXSTYLE, dwNewStyle);
  199.     if(nFlags != 0)
  200.     {
  201.         ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0,
  202.             SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags);
  203.     }
  204.  
  205.     return TRUE;
  206. }
  207.  
  208. BOOL CWindow::GetWindowText(BSTR& bstrText)
  209. {
  210.     USES_CONVERSION;
  211.     _ASSERTE(::IsWindow(m_hWnd));
  212.  
  213.     int nLen = ::GetWindowTextLength(m_hWnd);
  214.     if(nLen == 0)
  215.         return FALSE;
  216.  
  217.     LPTSTR lpszText = (LPTSTR)_alloca((nLen+1)*sizeof(TCHAR));
  218.  
  219.     if(!::GetWindowText(m_hWnd, lpszText, nLen+1))
  220.         return FALSE;
  221.  
  222.     bstrText = ::SysAllocString(T2OLE(lpszText));
  223.  
  224.     return (bstrText != NULL) ? TRUE : FALSE;
  225. }
  226.  
  227. HWND CWindow::GetTopLevelParent() const
  228. {
  229.     _ASSERTE(::IsWindow(m_hWnd));
  230.  
  231.     HWND hWndParent = m_hWnd;
  232.     HWND hWndTmp;
  233.     while((hWndTmp = ::GetParent(hWndParent)) != NULL)
  234.         hWndParent = hWndTmp;
  235.  
  236.     return hWndParent;
  237. }
  238.  
  239. HWND CWindow::GetTopLevelWindow() const
  240. {
  241.     _ASSERTE(::IsWindow(m_hWnd));
  242.  
  243.     HWND hWndParent = m_hWnd;
  244.     HWND hWndTmp = hWndParent;
  245.  
  246.     while(hWndTmp != NULL)
  247.     {
  248.         hWndTmp = (::GetWindowLong(hWndParent, GWL_STYLE) & WS_CHILD) ? ::GetParent(hWndParent) : ::GetWindow(hWndParent, GW_OWNER);
  249.         hWndParent = hWndTmp;
  250.     }
  251.  
  252.     return hWndParent;
  253. }
  254.  
  255. /////////////////////////////////////////////////////////////////////////////
  256. // CDynamicChain
  257.  
  258. CDynamicChain::~CDynamicChain()
  259. {
  260.     if(m_pChainEntry != NULL)
  261.     {
  262.         for(int i = 0; i < m_nEntries; i++)
  263.         {
  264.             if(m_pChainEntry[i] != NULL)
  265.                 delete m_pChainEntry[i];
  266.         }
  267.  
  268.         delete [] m_pChainEntry;
  269.     }
  270. }
  271.  
  272. BOOL CDynamicChain::SetChainEntry(DWORD dwChainID, CMessageMap* pObject, DWORD dwMsgMapID /* = 0 */)
  273. {
  274. // first search for an existing entry
  275.  
  276.     for(int i = 0; i < m_nEntries; i++)
  277.     {
  278.         if(m_pChainEntry[i] != NULL && m_pChainEntry[i]->m_dwChainID == dwChainID)
  279.         {
  280.             m_pChainEntry[i]->m_pObject = pObject;
  281.             m_pChainEntry[i]->m_dwMsgMapID = dwMsgMapID;
  282.             return TRUE;
  283.         }
  284.     }
  285.  
  286. // create a new one
  287.  
  288.     ATL_CHAIN_ENTRY* pEntry = NULL;
  289.     ATLTRY(pEntry = new ATL_CHAIN_ENTRY);
  290.  
  291.     if(pEntry == NULL)
  292.         return FALSE;
  293.  
  294. // search for an empty one
  295.  
  296.     for(i = 0; i < m_nEntries; i++)
  297.     {
  298.         if(m_pChainEntry[i] == NULL)
  299.         {
  300.             m_pChainEntry[i] = pEntry;
  301.             return TRUE;
  302.         }
  303.     }
  304.  
  305. // add a new one
  306.  
  307.     ATL_CHAIN_ENTRY** ppNew = NULL;
  308.     ATLTRY(ppNew = new ATL_CHAIN_ENTRY*[m_nEntries + 1]);
  309.  
  310.     if(ppNew == NULL)
  311.     {
  312.         delete pEntry;
  313.         return FALSE;
  314.     }
  315.  
  316.     pEntry->m_dwChainID = dwChainID;
  317.     pEntry->m_pObject = pObject;
  318.     pEntry->m_dwMsgMapID = dwMsgMapID;
  319.  
  320.     if(m_pChainEntry != NULL)
  321.     {
  322.         memcpy(ppNew, m_pChainEntry, m_nEntries * sizeof(ATL_CHAIN_ENTRY*));
  323.         delete [] m_pChainEntry;
  324.     }
  325.  
  326.     m_pChainEntry = ppNew;
  327.  
  328.     m_pChainEntry[m_nEntries] = pEntry;
  329.  
  330.     m_nEntries++;
  331.  
  332.     return TRUE;
  333. }
  334.  
  335. BOOL CDynamicChain::RemoveChainEntry(DWORD dwChainID)
  336. {
  337.     for(int i = 0; i < m_nEntries; i++)
  338.     {
  339.         if(m_pChainEntry[i] != NULL && m_pChainEntry[i]->m_dwChainID == dwChainID)
  340.         {
  341.             delete m_pChainEntry[i];
  342.             m_pChainEntry[i] = NULL;
  343.             return TRUE;
  344.         }
  345.     }
  346.  
  347.     return FALSE;
  348. }
  349.  
  350. BOOL CDynamicChain::CallChain(DWORD dwChainID, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult)
  351. {
  352.     for(int i = 0; i < m_nEntries; i++)
  353.     {
  354.         if(m_pChainEntry[i] != NULL && m_pChainEntry[i]->m_dwChainID == dwChainID)
  355.             return (m_pChainEntry[i]->m_pObject)->ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, m_pChainEntry[i]->m_dwMsgMapID);
  356.     }
  357.  
  358.     return FALSE;
  359. }
  360.  
  361. /////////////////////////////////////////////////////////////////////////////
  362. // CWndClassInfo
  363.  
  364. ATOM CWndClassInfo::Register(WNDPROC* pProc)
  365. {
  366.     if (m_atom == 0)
  367.     {
  368.         ::EnterCriticalSection(&_Module.m_csWindowCreate);
  369.         if(m_atom == 0)
  370.         {
  371.             HINSTANCE hInst = _Module.GetModuleInstance();
  372.             if (m_lpszOrigName != NULL)
  373.             {
  374.                 _ASSERTE(pProc != NULL);
  375.                 LPCTSTR lpsz = m_wc.lpszClassName;
  376.                 WNDPROC proc = m_wc.lpfnWndProc;
  377.  
  378.                 WNDCLASSEX wc;
  379.                 wc.cbSize = sizeof(WNDCLASSEX);
  380.                 if(!::GetClassInfoEx(NULL, m_lpszOrigName, &wc))
  381.                 {
  382.                     ::LeaveCriticalSection(&_Module.m_csWindowCreate);
  383.                     return 0;
  384.                 }
  385.                 memcpy(&m_wc, &wc, sizeof(WNDCLASSEX));
  386.                 pWndProc = m_wc.lpfnWndProc;
  387.                 m_wc.lpszClassName = lpsz;
  388.                 m_wc.lpfnWndProc = proc;
  389.             }
  390.             else
  391.             {
  392.                 m_wc.hCursor = ::LoadCursor(m_bSystemCursor ? NULL : hInst,
  393.                     m_lpszCursorID);
  394.             }
  395.  
  396.             m_wc.hInstance = hInst;
  397.             if (m_wc.lpszClassName == NULL)
  398.             {
  399.                 wsprintf(m_szAutoName, _T("ATL:%8.8X"), (DWORD)&m_wc);
  400.                 m_wc.lpszClassName = m_szAutoName;
  401.             }
  402.             WNDCLASSEX wcTemp;
  403.             memcpy(&wcTemp, &m_wc, sizeof(WNDCLASSEX));
  404. #ifdef BCC32_COMPAT
  405.             m_atom = (ATOM)::GetClassInfoEx(m_wc.hInstance, m_szAutoName, &wcTemp);
  406. #else
  407.             m_atom = ::GetClassInfoEx(m_wc.hInstance, m_szAutoName, &wcTemp);
  408. #endif
  409.             if (m_atom == 0)
  410.                 m_atom = ::RegisterClassEx(&m_wc);
  411.         }
  412.         ::LeaveCriticalSection(&_Module.m_csWindowCreate);
  413.     }
  414.  
  415.     if (m_lpszOrigName != NULL)
  416.     {
  417.         _ASSERTE(pProc != NULL);
  418.         _ASSERTE(pWndProc != NULL);
  419.         *pProc = pWndProc;
  420.     }
  421.     return m_atom;
  422. }
  423.  
  424. /////////////////////////////////////////////////////////////////////////////
  425. // CWindowImpl
  426.  
  427. LRESULT CALLBACK CWindowImplBase::StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  428. {
  429.     CWindowImplBase* pT = (CWindowImplBase*)_Module.ExtractCreateWndData();
  430.     _ASSERTE(pT != NULL);
  431.     pT->m_hWnd = hWnd;
  432.     pT->m_thunk.Init(WindowProc, pT);
  433.     WNDPROC pProc = (WNDPROC)&(pT->m_thunk.thunk);
  434.     ::SetWindowLong(hWnd, GWL_WNDPROC, (LONG)pProc);
  435.     // if somebody has subclassed us already we can't do anything,
  436.     // so discard return value from SetWindowLong
  437.     return pProc(hWnd, uMsg, wParam, lParam);
  438. }
  439.  
  440. LRESULT CALLBACK CWindowImplBase::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  441. {
  442. #ifdef _M_IX86
  443. #ifdef BCC32_COMPAT
  444.         hWnd = (HWND)_ECX;
  445. #else
  446.     __asm mov dword ptr[hWnd], ecx
  447. #endif // BCC32_COMPAT
  448. #endif
  449.     CWindowImplBase* pT = (CWindowImplBase*)hWnd;
  450.     LRESULT lRes;
  451.     BOOL bRet = pT->ProcessWindowMessage(pT->m_hWnd, uMsg, wParam, lParam, lRes, 0);
  452.     if(uMsg == WM_NCDESTROY)
  453.         pT->m_hWnd = NULL;
  454.     if(bRet)
  455.         return lRes;
  456.     return pT->DefWindowProc(uMsg, wParam, lParam);
  457. }
  458.  
  459. HWND CWindowImplBase::Create(HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName,
  460.         DWORD dwStyle, DWORD dwExStyle, UINT nID, ATOM atom)
  461. {
  462.     _ASSERTE(m_hWnd == NULL);
  463.  
  464.     if(atom == 0)
  465.         return NULL;
  466.  
  467.     _Module.AddCreateWndData(&m_thunk.cd, this);
  468.  
  469.     if(nID == 0 && (dwStyle & WS_CHILD))
  470.         nID = (UINT)this;
  471.  
  472.     HWND hWnd = ::CreateWindowEx(dwExStyle, (LPCTSTR)MAKELONG(atom, 0), szWindowName,
  473.         dwStyle, rcPos.left, rcPos.top, rcPos.right - rcPos.left,
  474.         rcPos.bottom - rcPos.top, hWndParent, (HMENU)nID,
  475.         _Module.GetModuleInstance(), NULL);
  476.  
  477.     _ASSERTE(m_hWnd == hWnd);
  478.  
  479.     return hWnd;
  480. }
  481.  
  482. BOOL CWindowImplBase::SubclassWindow(HWND hWnd)
  483. {
  484.     _ASSERTE(m_hWnd == NULL);
  485.     _ASSERTE(::IsWindow(hWnd));
  486.     m_thunk.Init(WindowProc, this);
  487.     WNDPROC pProc = (WNDPROC)&(m_thunk.thunk);
  488.     WNDPROC pfnWndProc = (WNDPROC)::SetWindowLong(hWnd, GWL_WNDPROC, (LONG)pProc);
  489.     if(pfnWndProc == NULL)
  490.         return FALSE;
  491.     m_pfnSuperWindowProc = pfnWndProc;
  492.     m_hWnd = hWnd;
  493.     return TRUE;
  494. }
  495.  
  496. HWND CWindowImplBase::UnsubclassWindow()
  497. {
  498.     _ASSERTE(m_hWnd != NULL);
  499.  
  500.     if(!::SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)m_pfnSuperWindowProc))
  501.         return NULL;
  502.  
  503.     m_pfnSuperWindowProc = ::DefWindowProc;
  504.  
  505.     HWND hWnd = m_hWnd;
  506.     m_hWnd = NULL;
  507.  
  508.     return hWnd;
  509. }
  510.  
  511. /////////////////////////////////////////////////////////////////////////////
  512. // CDialogImplBase
  513.  
  514. LRESULT CALLBACK CDialogImplBase::StartDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  515. {
  516.     CDialogImplBase* pT = (CDialogImplBase*)_Module.ExtractCreateWndData();
  517.     _ASSERTE(pT != NULL);
  518.     pT->m_hWnd = hWnd;
  519.     pT->m_thunk.Init(DialogProc, pT);
  520.     WNDPROC pProc = (WNDPROC)&(pT->m_thunk.thunk);
  521.     WNDPROC pOldProc = (WNDPROC)::SetWindowLong(hWnd, DWL_DLGPROC, (LONG)pProc);
  522.     // check if somebody has subclassed us already since we don't hold onto it
  523.     ATLTRACE(_T("Subclassing through a hook discarded.\n"));
  524.     return pProc(hWnd, uMsg, wParam, lParam);
  525. }
  526.  
  527. LRESULT CALLBACK CDialogImplBase::DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  528. {
  529. #ifdef _M_IX86
  530. #ifdef BCC32_COMPAT
  531.         hWnd = (HWND)_ECX;
  532. #else
  533.     __asm mov dword ptr[hWnd], ecx
  534. #endif // BCC32_COMPAT
  535. #endif
  536.     CDialogImplBase* pT = (CDialogImplBase*)hWnd;
  537.     LRESULT lRes;
  538.     if(pT->ProcessWindowMessage(pT->m_hWnd, uMsg, wParam, lParam, lRes, 0))
  539.     {
  540.         switch (uMsg)
  541.         {
  542.         case WM_COMPAREITEM:
  543.         case WM_VKEYTOITEM:
  544.         case WM_CHARTOITEM:
  545.         case WM_INITDIALOG:
  546.         case WM_QUERYDRAGICON:
  547.             return lRes;
  548.             break;
  549.         }
  550.         if (lRes != 0)
  551.             ::SetWindowLong(pT->m_hWnd, DWL_MSGRESULT, lRes);
  552.         return TRUE;
  553.     }
  554.     return FALSE;
  555. }
  556.  
  557. BOOL CDialogImplBase::EndDialog(int nRetCode)
  558. {
  559.     _ASSERTE(m_hWnd);
  560.     return ::EndDialog(m_hWnd, nRetCode);
  561. }
  562.  
  563. /////////////////////////////////////////////////////////////////////////////
  564. // CContainedWindow
  565.  
  566. LRESULT CALLBACK CContainedWindow::StartWindowProc(HWND hWnd, UINT uMsg,
  567.     WPARAM wParam, LPARAM lParam)
  568. {
  569.     CContainedWindow* pThis = (CContainedWindow*)_Module.ExtractCreateWndData();
  570.     _ASSERTE(pThis != NULL);
  571.     pThis->m_hWnd = hWnd;
  572.     pThis->m_thunk.Init(pThis->WindowProc, pThis);
  573.     WNDPROC pProc = (WNDPROC)&(pThis->m_thunk.thunk);
  574.     WNDPROC pOldProc = (WNDPROC)::SetWindowLong(hWnd, GWL_WNDPROC, (LONG)pProc);
  575.     // check if somebody has subclassed us already since we don't hold onto it
  576.     ATLTRACE(_T("Subclassing through a hook discarded.\n"));
  577.     return pProc(hWnd, uMsg, wParam, lParam);
  578. }
  579.  
  580. LRESULT CALLBACK CContainedWindow::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam,
  581.     LPARAM lParam)
  582. {
  583. #ifdef _M_IX86
  584. #ifdef BCC32_COMPAT
  585.         hWnd = (HWND)_ECX;
  586. #else
  587.     __asm mov dword ptr[hWnd], ecx
  588. #endif // BCC32_COMPAT
  589. #endif
  590.     CContainedWindow* pT = (CContainedWindow*)hWnd;
  591.     _ASSERTE(pT->m_hWnd != NULL);
  592.     _ASSERTE(pT->m_pObject != NULL);
  593.  
  594.     LRESULT lRes;
  595.     BOOL bRet = pT->m_pObject->ProcessWindowMessage(pT->m_hWnd, uMsg, wParam, lParam, lRes, pT->m_dwMsgMapID);
  596.     if(uMsg == WM_NCDESTROY)
  597.         pT->m_hWnd = NULL;
  598.     if(bRet)
  599.         return lRes;
  600.     return pT->DefWindowProc(uMsg, wParam, lParam);
  601. }
  602.  
  603. ATOM CContainedWindow::RegisterWndSuperclass()
  604. {
  605.     ATOM atom = 0;
  606.     LPTSTR szBuff = (LPTSTR)_alloca((lstrlen(m_lpszClassName) + 14) * sizeof(TCHAR));
  607.  
  608.     WNDCLASSEX wc;
  609.     wc.cbSize = sizeof(WNDCLASSEX);
  610.  
  611.     if(::GetClassInfoEx(NULL, m_lpszClassName, &wc))
  612.     {
  613.         m_pfnSuperWindowProc = wc.lpfnWndProc;
  614.  
  615.         wsprintf(szBuff, _T("ATL:%s"), m_lpszClassName);
  616.  
  617.         WNDCLASSEX wc1;
  618.         wc1.cbSize = sizeof(WNDCLASSEX);
  619.         atom = (ATOM)::GetClassInfoEx(_Module.GetModuleInstance(), szBuff, &wc1);
  620.  
  621.         if(atom == 0)   // register class
  622.         {
  623.             wc.lpszClassName = szBuff;
  624.             wc.lpfnWndProc = StartWindowProc;
  625.             wc.hInstance = _Module.GetModuleInstance();
  626.  
  627.             atom = ::RegisterClassEx(&wc);
  628.         }
  629.     }
  630.  
  631.     return atom;
  632. }
  633.  
  634. HWND CContainedWindow::Create(HWND hWndParent, RECT& rcPos,
  635.     LPCTSTR szWindowName, DWORD dwStyle, DWORD dwExStyle, UINT nID)
  636. {
  637.     _ASSERTE(m_hWnd == NULL);
  638.  
  639.     ATOM atom = RegisterWndSuperclass();
  640.     if(atom == 0)
  641.         return NULL;
  642.  
  643.     _Module.AddCreateWndData(&m_thunk.cd, this);
  644.  
  645.     if(nID == 0 && (dwStyle & WS_CHILD))
  646.         nID = (UINT)this;
  647.  
  648.     HWND hWnd = ::CreateWindowEx(dwExStyle, (LPCTSTR)MAKELONG(atom, 0), szWindowName,
  649.                             dwStyle,
  650.                             rcPos.left, rcPos.top,
  651.                             rcPos.right - rcPos.left,
  652.                             rcPos.bottom - rcPos.top,
  653.                             hWndParent, (HMENU)nID,
  654.                             _Module.GetModuleInstance(), this);
  655.  
  656.     _ASSERTE(m_hWnd == hWnd);
  657.     return hWnd;
  658. }
  659.  
  660. BOOL CContainedWindow::SubclassWindow(HWND hWnd)
  661. {
  662.     _ASSERTE(m_hWnd == NULL);
  663.     _ASSERTE(::IsWindow(hWnd));
  664.  
  665.     m_thunk.Init(WindowProc, this);
  666.     WNDPROC pProc = (WNDPROC)&m_thunk.thunk;
  667.     WNDPROC pfnWndProc = (WNDPROC)::SetWindowLong(hWnd, GWL_WNDPROC, (LONG)pProc);
  668.     if(pfnWndProc == NULL)
  669.         return FALSE;
  670.     m_pfnSuperWindowProc = pfnWndProc;
  671.     m_hWnd = hWnd;
  672.     return TRUE;
  673. }
  674.  
  675. HWND CContainedWindow::UnsubclassWindow()
  676. {
  677.     _ASSERTE(m_hWnd != NULL);
  678.  
  679.     if(!::SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)m_pfnSuperWindowProc))
  680.         return NULL;
  681.     m_pfnSuperWindowProc = ::DefWindowProc;
  682.  
  683.     HWND hWnd = m_hWnd;
  684.     m_hWnd = NULL;
  685.  
  686.     return hWnd;
  687. }
  688.  
  689. #ifndef ATL_NO_NAMESPACE
  690. }; //namespace ATL
  691. #endif
  692.  
  693. ///////////////////////////////////////////////////////////////////////////////
  694. //All Global stuff goes below this line
  695. ///////////////////////////////////////////////////////////////////////////////
  696.